package com.wei.czz.framework.admin.manager;

import com.wei.czz.common.constant.Constant;
import com.wei.czz.common.constant.EntityConstant;
import com.wei.czz.common.constant.RedisConstant;
import com.wei.czz.common.dto.admin.userConfig.UserConfigTreeDto;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.common.multiDIct.MultiDictEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.utils.CopyUtils;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.vo.admin.userConfig.UserConfigVo;
import com.wei.czz.framework.admin.entity.UserConfigEntity;
import com.wei.czz.framework.admin.service.UserConfigService;
import com.wei.czz.framework.common.entity.MultiDictEntity;
import com.wei.czz.framework.common.helper.CacheHelper;
import com.wei.czz.framework.common.handler.DebounceHandler;
import com.wei.czz.framework.common.service.AsyncService;
import com.wei.czz.framework.common.service.MultiDictService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2024-05-31 09:57:30
 * className: UserConfigManager
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class UserConfigManager {

    private static final Logger log = LoggerFactory.getLogger(UserConfigManager.class);

    private final UserConfigService userConfigService;

    private final MultiDictService multiDictService;

    private final CacheHelper cacheHelper;

    private final AsyncService asyncService;

    private final DebounceHandler debounceHandler;

    public void saveUserConfig(UserConfigVo userConfigVo) {
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        /*
            判断配置是否存在
         */
        List<MultiDictEntity> multiDictList = multiDictService.findChildrenList(MultiDictEnum.USER_CONFIG);
        MultiDictEntity _multiDict = multiDictList.stream()
                .filter(multiDict -> multiDict.getValue().equals(userConfigVo.getConfigKey()))
                .findFirst()
                .orElse(null);
        if (Objects.isNull(_multiDict)) {
            log.info("用户配置键不存在");
            throw new CzzException();
        }
        if (CommonEnum.ONE.getValue().equals(_multiDict.getStatus())) {
            log.info("用户配置键不存在");
            throw new CzzException();
        }

        /*
            获取用户配置
         */
        UserConfigEntity userConfig = userConfigService.get(userPo.getUserId(), userConfigVo.getConfigKey());
        if (Objects.isNull(userConfig)) {
            /*
                保存用户配置
             */
            userConfig = new UserConfigEntity();
            userConfig.setUserId(userPo.getUserId())
                    .setConfigKey(userConfigVo.getConfigKey())
                    .setConfigValue(userConfigVo.getConfigValue())
                    .setStatus(CommonEnum.ZERO.getValue())
                    .setDeleteStatus(CommonEnum.ZERO.getValue())
                    .setUpdateTime(date)
                    .setUpdateUser(StringUtils.EMPTY)
                    .setUpdateUserId(CommonEnum.ZERO.getLongValue())
                    .setCreateTime(date)
                    .setCreateUser(userPo.getUsername())
                    .setCreateUserId(userPo.getUserId());
            userConfigService.saveOrEdit(userConfig);
        } else {
            // 删除缓存
            String cacheKey = RedisConstant.STRING + EntityConstant.USER_CONFIG + Constant.SPLIT
                    + userPo.getUserId() + Constant.SPLIT + userConfigVo.getConfigKey();
            cacheHelper.delete(cacheKey);

            UserConfigEntity updateUserConfig = new UserConfigEntity();
            updateUserConfig.setId(userConfig.getId())
                    .setConfigValue(userConfigVo.getConfigValue())
                    .setUpdateTime(date)
                    .setUpdateUser(userPo.getUsername())
                    .setUpdateUserId(userPo.getUserId());
            userConfigService.saveOrEdit(updateUserConfig);

            // 延时双删
            Runnable runnable = () -> {
                // 删除缓存
                cacheHelper.delete(cacheKey);
            };
            debounceHandler.debounceRun(runnable, cacheKey, 1500, TimeUnit.MILLISECONDS);
        }

    }

    public String getUserConfig(String configKey) {
        // 获取操作用户主键
        Long optUserId = SecurityUtils.getUserId();

        String cacheKey = RedisConstant.STRING + EntityConstant.USER_CONFIG + Constant.SPLIT + optUserId +
                Constant.SPLIT + configKey;

        String configValue = cacheHelper.get(cacheKey);
        if (StringUtils.isNotBlank(configValue)) {
            return configValue;
        }

        /*
            获取用户配置
         */
        UserConfigEntity userConfig = userConfigService.get(optUserId, configKey);
        if (Objects.isNull(userConfig)) {
            log.info("用户配置不存在。userId={} configKey={}", optUserId, configKey);
            return StringUtils.EMPTY;
        }

        configValue = userConfig.getConfigValue();

        /*
            添加缓存
         */
        cacheHelper.cache(cacheKey, configValue);

        return configValue;
    }

    public List<UserConfigTreeDto> getUserConfigTree() {
        // 获取操作用户主键
        Long optUserId = SecurityUtils.getUserId();

        /*
            获取级联字典
         */
        List<MultiDictEntity> multiDictList = multiDictService.findChildrenList(MultiDictEnum.USER_CONFIG);

        /*
            获取用户配置
         */
        List<UserConfigEntity> userConfigList = userConfigService.findList(optUserId);
        Map<String, String> userConfigMap = CopyUtils.listToMap(
                userConfigList, UserConfigEntity::getConfigKey, UserConfigEntity::getConfigValue, (o1, o2) -> o2
        );

        /*
            数据构造
         */
        List<UserConfigTreeDto> resultList = new ArrayList<>();
        List<UserConfigTreeDto> lastOptList = new ArrayList<>();
        Map<String, UserConfigTreeDto> map = new HashMap<>();

        for (MultiDictEntity multiDict : multiDictList) {
            if (CommonEnum.ONE.getValue().equals(multiDict.getStatus())) {
                log.info("级联字典状态不可用。id={}", multiDict.getId());
                continue;
            }
            UserConfigTreeDto userConfigTreeDto = new UserConfigTreeDto();
            userConfigTreeDto.setId(multiDict.getId().toString())
                    .setParentId(multiDict.getParentId().toString())
                    .setConfigName(multiDict.getName())
                    .setConfigKey(multiDict.getValue())
                    .setConfigValue(userConfigMap.get(multiDict.getValue()))
                    .setSort(multiDict.getSort());

            map.put(userConfigTreeDto.getId(), userConfigTreeDto);

            UserConfigTreeDto parentUserConfig = map.get(userConfigTreeDto.getParentId());
            if (Objects.isNull(parentUserConfig)) {
                lastOptList.add(userConfigTreeDto);
                continue;
            }
            TreeSet<UserConfigTreeDto> children = parentUserConfig.getChildren();
            if (Objects.isNull(children)) {
                children = new TreeSet<>();
                parentUserConfig.setChildren(children);
            }
            children.add(userConfigTreeDto);
        }
        for (UserConfigTreeDto userConfigTreeDto : lastOptList) {
            UserConfigTreeDto parentUserConfig = map.get(userConfigTreeDto.getParentId());
            if (Objects.isNull(parentUserConfig)) {
                log.info("（用户配置）父级级联字典不存在。{}", userConfigTreeDto);
                continue;
            }
            TreeSet<UserConfigTreeDto> children = parentUserConfig.getChildren();
            if (Objects.isNull(children)) {
                children = new TreeSet<>();
                parentUserConfig.setChildren(children);
            }
            children.add(userConfigTreeDto);
        }

        return resultList;
    }
}
